# Copyright 2008 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#     http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.api import urlfetch

import urllib
import json
import logging
import datetime
import re

from dbmodel import User

class ApiServer(webapp.RequestHandler):

  def get(self):
    """
    Handle GET requests
    """
    portions = self.request.path.split("/")
    resp = self._getFail("The %s method is undefined." % portions[2])

    self.response.headers['Content-Type'] = "text/plain"
    self.response.out.write(json.write(resp))


  def post(self):
    """
    Handle POST requests
    """
    portions = self.request.path.split("/")
      
    if (portions[2] == "setlocation"):
      resp = self.setLocation()
    elif (portions[2] == "getlocations"):
      resp = self.getLocations()
    else:
      resp = self._getFail("The %s method is undefined." % portions[2])

    self.response.out.write(json.write(resp))


  def _getFail(self, message, payload=None):
    """
    Returns a response indicating a failure, with the given message and payload
    """
    fail =  { "status" : "failure",
              "message" : message }
    if payload != None:
      fail["payload"] = payload
    return fail


  def _getSuccess(self, message="", payload=None):
    """
    Returns a response indicating a success, with the given message and payload
    """
    succ = { "status" : "success",
             "message" : message }
    if payload != None:
      succ["payload"] = payload
    return succ


  def _mapId(self, container_id, user_id):
    """
    Returns an ID uniquely representing a user on the web, given their 
    container's ID and their user ID
    """
    return ":".join([container_id, user_id])


  def setLocation(self): 
    """
    Saves location data for the current viewer to the datastore
    TODO: Verify the signature on the request!
    """   
    viewer_id = self.request.get("opensocial_viewer_id")
    if not viewer_id:
      return self._getFail("Viewer not available")
      
    lat = self.request.get("latitude").encode('utf-8')
    if not lat:
      return self._getFail("Latitude was not supplied")
      
    lng = self.request.get("longitude").encode('utf-8')
    if not lng:
      return self._getFail("Longitude was not supplied")
        
    container = self.request.get("oauth_consumer_key")
    if not container:
      return self._getFail("Container was not available")
      
    thumbnail_url = self.request.get("thumbnail_url")
    if not thumbnail_url:
      return self._getFail("Thumbnail was not supplied")
      
    viewer_name = self.request.get("viewer_name")
    if not viewer_name:
      return self._getFail("Thumbnail was not supplied")

    #OpenSocial ID is a combination of container name and user id
    opensocial_id = self._mapId(container, viewer_id)

    #Attempt to retrieve the user but create a new one if it is not found
    user = db.GqlQuery("SELECT * FROM User WHERE opensocial_id = :1 LIMIT 1",
               opensocial_id).get()
    if not user:
      user = User()
    
    #Update the fields of the user and save
    user.latitude = lat
    user.longitude = lng
    user.name = viewer_name  
    user.thumbnail_url = thumbnail_url
    user.opensocial_id = opensocial_id
    db.put(user)

    return self._getSuccess("Updated the location.", user.toJson())

  def getLocations(self):
    """
    Returns the information for all supplied users
    """
    container = self.request.get("oauth_consumer_key")
    if not container:
      return self._getFail("Container was not available")
      
    ids = self.request.get("user_ids")
    if not ids:
      return self._getFail("No IDs were supplied")
      
    ids = ids.split(",")
    mappedids = []
    for user_id in ids:
      mappedids.append(self._mapId(container, user_id))
        
    #TODO: This query only good up to 40 mappedids - split to multiple if over                  
    users = db.GqlQuery("SELECT * FROM User WHERE opensocial_id IN :1", mappedids).fetch(100)
    
    if len(users) > 0: 
      resp = self._getSuccess("Found users", [])
      for user in users:
        resp["payload"].append(user.toJson())  
    else:
      resp = self._getSuccess("Could not find any user data", [])

    return resp
      


